package tsp;

import geotag.AddressTaggedState;
import geotag.Geotagger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.*;

import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.xml.sax.SAXException;

import tsp.algorithms.ClockwiseTraveller;

@SuppressWarnings("serial")
public class RoutePlannerServlet extends HttpServlet
{

	public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException
	{
		/* Check that we have a file upload request */
		if (ServletFileUpload.isMultipartContent(req) == false)
		{
			/*
			 * Nope, don't have a file, so there's nothing to do (eventually
			 * send back to the original html page.
			 */

			return;
		}

		List<Waypoint> wayPointsToMap = new ArrayList<Waypoint>();
		/*
		 * If we're here, we have a file to process
		 */
		try
		{
			ServletFileUpload upload = new ServletFileUpload();
			FileItemIterator iter = upload.getItemIterator(req);

			StringBuffer stringBuffer = new StringBuffer();
			String startAddress = "";

			while (iter.hasNext())
			{
				FileItemStream item = iter.next();
				InputStream stream = item.openStream();
				if (item.isFormField())
				{
					startAddress = Streams.asString(stream);
				}
				else
				{
					BufferedReader br = new BufferedReader(new InputStreamReader(stream));
					String line = null;
					while ((line = br.readLine()) != null)
					{
						stringBuffer.append(line).append("\n");
					}

					br.close();
				}
			}

			/* Now we can process the file */
			wayPointsToMap = processFile(startAddress,
											stringBuffer.toString());

		}
		catch (FileUploadException e)
		{
			e.printStackTrace();
		}

		/*
		 * Okay, now if we have more than three entries in the waypoints array,
		 * we can continue.
		 */

		if (wayPointsToMap.size() > 2)
		{
			req.setAttribute("waypoints", wayPointsToMap);

			ServletContext sc = getServletContext();
			RequestDispatcher rd = sc.getRequestDispatcher("/directions.jsp");
			try
			{
				rd.forward(req, resp);
			}
			catch (ServletException e)
			{
				e.printStackTrace();
			}
		}
	}

	private List<Waypoint> processFile(String startAddress, String fileContents)
	{
		GPXParser gpxParser;
		try
		{
			gpxParser = new GPXParser(fileContents);
			List<Waypoint> wayPoints = gpxParser.getWaypoints();

			/*
			 * Add the start point as the first one in the list if there's
			 * anything there
			 */
			Geotagger gt = new Geotagger(startAddress);
			String startPoint = gt.getTaggedCoordinates();
			
			if (gt.getTaggedState() != AddressTaggedState.INVALID_LOCATION && startPoint.contains(","))
			{
				String[] coordinates = startPoint.split(",");
				wayPoints.add(0, new Waypoint(	Double.valueOf(coordinates[0]),
												Double.valueOf(coordinates[1]),
												"Start Point",
												"Start point"));
			}

			/* Now put them in order */
			ClockwiseTraveller clockwiseAlgo = new ClockwiseTraveller(wayPoints);
			return clockwiseAlgo.getSortedWaypoints();
		}
		catch (SAXException e)
		{
			System.err.println("hmm: got " + e.getMessage());
			e.printStackTrace();
		}
		catch (IOException e)
		{
			System.err.println("hmm: got " + e.getMessage());
			e.printStackTrace();
		}

		/* Should not get here */
		return null;
	}
}
